package com.wbpay.sdk.framework;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.widget.EditText;

import com.wbpay.sdk.WbSdk;
import com.wbpay.sdk.dlg.ExitDialog;
import com.wbpay.sdk.dlg.LoginDialog;
import com.wbpay.sdk.dlg.ProgressMsgDialog;
import com.wbpay.sdk.dlg.RegisterDialog;
import com.wbpay.sdk.dlg.UserCenterDialog;
import com.wbpay.sdk.dlg.WebViewDialog;
import com.wbpay.sdk.http.Response;
import com.wbpay.sdk.listener.OnUserExchangeListener;
import com.wbpay.sdk.listener.OnUserLoginListener;
import com.wbpay.sdk.listener.OnUserLogoutListener;
import com.wbpay.sdk.model.SdkInfo;
import com.wbpay.sdk.params.User;
import com.wbpay.sdk.request.IUserRequest;
import com.wbpay.sdk.request.UserRequestImpl;
import com.wbpay.sdk.user.UserManager;
import com.wbpay.sdk.utils.Log;
import com.wbpay.sdk.utils.ParamsValidator;
import com.wbpay.sdk.utils.Utils;
import com.wbpay.sdk.widget.AccountPopup;

import java.util.List;

/**
 * 用户业务处理
 */

public class UserModule implements IUserFunction, IUserLogin {

    private Context mContext;
    private LoginDialog mLoginDialog;
    private IUserRequest mUserRequest;
    private ProgressMsgDialog mProgressDialog;
    private Handler mHandler;
    private OnUserLoginListener mOnUserLoginListener;
    private RegisterDialog mRegisterDialog;
    private String mTmpAccount;
    private String mTmpPassoword;
    private OnUserExchangeListener mOnUserExchangeListener;
    private OnUserLogoutListener mOnUserLogoutListener;

    public UserModule(Context context) {
        if (!(context instanceof Activity)) {
            throw new IllegalArgumentException("Context must be an Activity");
        }
        mContext = context;
        mHandler = new Handler(context.getMainLooper());
        mUserRequest = new UserRequestImpl(context);
        mProgressDialog = new ProgressMsgDialog(mContext);
        checkUserLoginExpire();
    }

    public void setOnUserLoginListener(OnUserLoginListener l) {
        mOnUserLoginListener = l;
    }

    public void setOnUserExchangeListener(OnUserExchangeListener l) {
        mOnUserExchangeListener = l;
    }

    @Override
    public void showLogin() {
        mLoginDialog = new LoginDialog(mContext, this);
        mLoginDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                if (mOnUserExchangeListener != null) {
                    mOnUserExchangeListener.onExchangeComplete(false, null);
                    mOnUserExchangeListener = null;
                } else if (mOnUserLoginListener != null) {
                    mOnUserLoginListener.onLoginComplete(false, null);
                    mOnUserLoginListener = null;
                }
            }
        });
        mLoginDialog.show();
    }

    /**
     * 检查登录是否已过期
     */
    private void checkUserLoginExpire() {
        long lastLoginTime = UserManager.get(mContext).getLoginTime();
        if (System.currentTimeMillis() - lastLoginTime > SdkInfo.get(mContext).getLoginExpireTime()) {
            UserManager.get(mContext).setCurrentUser(new User());
        }
    }

    private boolean autoLogin() {
        User user = UserManager.get(mContext).loadCurrentUser();
        if (user == null || TextUtils.isEmpty(user.getUsername())) {
            return false;
        }
        long lastLoginTime = UserManager.get(mContext).getLoginTime();
        // 自动登录已经超时，请选择手动登录
        if (System.currentTimeMillis() - lastLoginTime > SdkInfo.get(mContext).getLoginExpireTime()) {
            UserManager.get(mContext).setCurrentUser(new User());
            return false;
        }
        List<User> list = loadUsers();
        User lastUser = null;
        if (list != null && list.size() > 0) {
            lastUser = list.get(list.size() - 1);
        }
        if (lastUser != null && !TextUtils.isEmpty(lastUser.getUsername()) && !TextUtils.isEmpty(lastUser.getPassword())) {
            loginInternal(lastUser.getUsername(), lastUser.getPassword(), true, true);
            return true;
        }
        return false;
    }

    /**
     * 显示进度框
     *
     * @param styleTitle
     * @param title
     * @param content
     */
    private void showProgress(final CharSequence styleTitle, final String title, final String content) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mProgressDialog.setProgressContent(title, content);
                mProgressDialog.setStyleTitle(styleTitle);
                mProgressDialog.show();
            }
        });
    }

    /**
     * 显示进度框结果，并关闭
     *
     * @param success
     * @param tips
     * @param delayClose
     */
    private void showResult(final boolean success, final String tips, final boolean delayClose) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (mProgressDialog != null && mProgressDialog.isShowing()) {
                    if (success) {
                        mProgressDialog.setSuccessMessage(tips, delayClose);
                    } else {
                        mProgressDialog.setFailureMessage(tips);
                    }
                }
            }
        });
    }

    /**
     * 验证用户名的合法性
     *
     * @param username
     * @return
     */
    private boolean verifyUsername(String username) {
        boolean pass = true;
        try {
            ParamsValidator.checkUsername(username);
        } catch (IllegalArgumentException e) {
            if (mLoginDialog != null) {
                mLoginDialog.setAccountError(e.getMessage());
            }
            if (mRegisterDialog != null) {
                mRegisterDialog.setAccountError(e.getMessage());
            }
            pass = false;
        }
        return pass;
    }

    /**
     * 制作账号风格标题
     *
     * @param account
     * @return
     */
    private SpannableStringBuilder makeTitleStyle(String account) {
        String prefix = mContext.getString(Utils.getStringId(mContext,
                "jy_dologin_dialog_9you_user"));
        String suffix = mContext.getString(Utils.getStringId(mContext,
                "jy_dologin_dialog_welcome"));
        SpannableStringBuilder style = new SpannableStringBuilder(prefix
                + account + suffix);
        style.setSpan(
                new ForegroundColorSpan(mContext.getResources().getColor(
                        Utils.getColorId(mContext,
                                "jy_color_9you_login_blue"))), prefix.length(),
                prefix.length() + account.length(),
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return style;
    }

    /**
     * 保存账户密码
     */
    private void rememberAccount(String username, String password, boolean remember, boolean autoLogin) {
        // 非自动登录下保存用户名和密码
        if (!autoLogin) {
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            if (remember) {
                UserManager.get(mContext).saveUser(user);
            } else {
                UserManager.get(mContext).removeUser(user);
            }
            UserManager.get(mContext).setRememberPassword(remember);
        }
    }

    /**
     * 通知登陆的结果
     *
     * @param success
     * @param user
     * @param tips
     */
    private void notifyLoginResult(final boolean success, final User user, String tips, boolean autoLogin) {
        Log.d(Log.TAG, "success : " + success);
        showResult(success, tips, true);
        if (success) {
            UserManager.get(mContext).setCurrentUser(user);
            if (!autoLogin) {
                // 记录手动登录成功的时间
                Log.d(Log.TAG, "Record Login Time");
                UserManager.get(mContext).setLoginTime();
            }
        }
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (success) {
                    if (mLoginDialog != null) {
                        mLoginDialog.dismiss();
                        mLoginDialog = null;
                    }
                }
                if (mOnUserLoginListener != null) {
                    mOnUserLoginListener.onLoginComplete(success, user != null ? user.toString() : null);
                    mOnUserLoginListener = null;
                }
            }
        });
    }

    @Override
    public void doLogin(final String username, final String password, final boolean rememberPwd) {
        loginInternal(username, password, rememberPwd, false);
    }

    /**
     * 执行登录请求
     *
     * @param username
     * @param password
     * @param remember
     * @param autoLogin
     */
    private void loginInternal(final String username, final String password,
                               final boolean remember, final boolean autoLogin) {
        Log.d(Log.TAG, "username : " + username);
        if (verifyUsername(username) && verifyPassword(password)) {
            CharSequence styleTitle = makeTitleStyle(username);
            String content = mContext.getString(Utils.getStringId(mContext,
                    "jy_dologin_dialog_login"));
            showProgress(styleTitle, null, content);
            mUserRequest.login(username, password, new ResponseCallback<User>() {
                @Override
                public void onCallback(Response<User> response) {
                    boolean success = false;
                    String tips = null;
                    User user = null;
                    if (response == null) {
                        success = false;
                        tips = mContext.getString(Utils.getStringId(mContext, "jy_login_failed"));
                    } else {
                        success = "00".equals(response.getCode());
                        if (success) { // 登陆成功
                            user = response.getObj();
                            tips = mContext.getString(Utils.getStringId(mContext, "jy_login_success"));
                        } else { // 登陆失败
                            tips = response.getMsg();
                        }
                    }
                    if (success) { // 登录成功后，记录登录账户
                        rememberAccount(username, password, remember, autoLogin);
                    }
                    notifyLoginResult(success, user, tips, autoLogin);
                }
            });
        }
    }

    @Override
    public void callRegister() {
        if (mLoginDialog != null && mLoginDialog.isShowing()) {
            mLoginDialog.dismiss();
            mLoginDialog = null;
        }
        showRegisterView();
    }

    private void showRegisterView() {
        mRegisterDialog = new RegisterDialog(mContext, this);
        mRegisterDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                mRegisterDialog = null;
                showLogin();
            }
        });
        mRegisterDialog.show();
    }

    /**
     * 验证密码的合法性
     *
     * @param password
     * @return
     */
    private boolean verifyPassword(String password) {
        boolean pass = true;
        try {
            ParamsValidator.checkPwd(password);
        } catch (IllegalArgumentException e) {
            if (mRegisterDialog != null) {
                mRegisterDialog.setPasswordError(e.getMessage());
            }
            if (mLoginDialog != null) {
                mLoginDialog.setAccountError(e.getMessage());
            }
            pass = false;
        }
        return pass;
    }

    /**
     * 验证手机号码
     *
     * @param cellphone
     * @return
     */
    private boolean verifyCellphone(String cellphone) {
        boolean pass = true;
        try {
            ParamsValidator.checkTelphone(cellphone);
        } catch (IllegalArgumentException e) {
            if (mRegisterDialog != null) {
                mRegisterDialog.setAccountError(e.getMessage());
            }
            if (mLoginDialog != null) {
                mLoginDialog.setAccountError(e.getMessage());
            }
            pass = false;
        }
        return pass;
    }

    /**
     * 验证验证码
     *
     * @param captcha
     * @return
     */
    private boolean verifyCaptcha(String captcha) {
        if (TextUtils.isEmpty(captcha)) {
            String error = mContext.getString(Utils.getStringId(mContext,
                    "jy_activity_sms_verify_empty"));
            mRegisterDialog.setCaptchaError(error);
            return false;
        }
        return true;
    }

    /**
     * 通知验证码发送结果
     *
     * @param success
     * @param tips
     */
    private void notifyCaptchaFetchResult(boolean success, String tips) {
        Log.d(Log.TAG, "success : " + success);
        showResult(success, tips, true);
        if (success) {
            // 保存发送验证码成功的时间，方便倒计时
            mRegisterDialog.setLastSmsCaptchaTime();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mRegisterDialog.setCountDown(60000);
                }
            });
        }
    }

    /**
     * 执行获取验证码代码
     *
     * @param telphone
     */
    private void fetchCaptchaInternal(String telphone) {
        if (verifyCellphone(telphone)) {
            mUserRequest.fetchCaptcha(telphone, new ResponseCallback<Void>() {
                @Override
                public void onCallback(Response<Void> response) {
                    String tips = null;
                    boolean success = false;
                    if (response == null) {
                        success = false;
                        tips = mContext.getString(Utils.getStringId(mContext, "jy_activity_sms_send_fail"));
                    } else {
                        if ("00".equals(response.getCode())) {
                            // 获取验证码成功
                            success = true;
                            tips = mContext.getString(Utils.getStringId(mContext, "jy_activity_sms_verify_success"));
                        } else {
                            tips = response.getMsg();
                        }
                    }
                    notifyCaptchaFetchResult(success, tips);
                }
            });
        }
    }

    @Override
    public void fetchCaptcha(String telphone) {
        if (verifyCellphone(telphone)) {
            String title = mContext.getResources().getString(Utils.getStringId(mContext, "jy_activity_sms_verify_get"));
            String content = mContext.getResources().getString(Utils.getStringId(mContext, "jy_activity_sms_sending"));
            showProgress(null, title, content);
            checkRegisterUser(telphone);
        }
    }

    /**
     * 通知验证码验证结果
     *
     * @param success
     * @param tips
     */
    private void notifyCaptchaCheckResult(boolean success, String tips) {
        Log.d(Log.TAG, "success : " + success + " , tips : " + tips);
        if (success) {
            registerByCallphoneInternal(mTmpAccount, mTmpPassoword);
        } else {
            showResult(success, tips, false);
        }
    }

    @Override
    public void checkCaptcha(final String telphone, final String captcha) {
        if (verifyCellphone(telphone) && verifyCaptcha(captcha)) {
            mUserRequest.verifyCaptcha(telphone, captcha, new ResponseCallback<Void>() {
                @Override
                public void onCallback(Response<Void> response) {
                    boolean success = false;
                    String tips = null;
                    if (response == null) {
                        success = false;
                        tips = mContext.getString(Utils.getStringId(mContext, "jy_activity_sms_verify_failed"));
                    } else {
                        success = "00".equals(response.getCode());
                        if (success) { // 验证码验证成功
                            tips = mContext.getString(Utils.getStringId(mContext, "jy_activity_sms_verify_sussess"));
                        } else { // 验证码验证失败
                            tips = response.getMsg();
                        }
                    }
                    // TODO: 测试数据，让所有验证码均为验证成功状态
                    // success = true;
                    notifyCaptchaCheckResult(success, tips);
                }
            });
        }
    }

    /**
     * 通知注册成功
     *
     * @param success
     * @param user
     * @param tips
     */
    private void notifyRegisterResult(boolean success, final User user, String tips) {
        Log.d(Log.TAG, "success : " + success + " , tips : " + tips);
        showResult(success, tips, false);
        if (success) {
            if (mRegisterDialog != null && mRegisterDialog.isShowing()) {
                mRegisterDialog.dismiss();
                mRegisterDialog = null;
            }
            // 注册成功后，执行自动登录功能
            loginInternal(mTmpAccount, mTmpPassoword, true, false);
        }
    }

    /**
     * 执行手机号注册
     *
     * @param telphone
     * @param password
     */
    private void registerByCallphoneInternal(String telphone, String password) {
        Log.d(Log.TAG, "telphone : " + telphone);
        if (verifyCellphone(telphone) && verifyPassword(password)) {
            mUserRequest.registerByTelephne(telphone, password, new ResponseCallback<User>() {
                @Override
                public void onCallback(Response<User> response) {
                    boolean success = false;
                    String tips = null;
                    User user = null;
                    if (response == null) {
                        success = false;
                        tips = mContext.getString(Utils.getStringId(mContext, "jy_reg_failed"));
                    } else {
                        success = "00".equals(response.getCode());
                        if (success) { // 注册成功
                            user = response.getObj();
                            tips = mContext.getString(Utils.getStringId(mContext, "jy_reg_success"));
                        } else { // 注册失败
                            tips = response.getMsg();
                        }
                    }
                    notifyRegisterResult(success, user, tips);
                }
            });
        }
    }

    /**
     * 通知检查手机号的结果
     *
     * @param success
     * @param tips
     */
    private void notifyCheckRegisterUserResult(boolean success, String tips, String telphone) {
        if (success) {
            fetchCaptchaInternal(telphone);
        } else {
            showResult(success, tips, false);
        }
    }

    /**
     * 检查手机号码是否可用
     *
     * @param telphone
     */
    private void checkRegisterUser(final String telphone) {
        if (verifyCellphone(telphone)) {
            mUserRequest.checkRegisterUser(telphone, new ResponseCallback<Void>() {
                @Override
                public void onCallback(Response<Void> response) {
                    boolean success = false;
                    String tips = null;
                    if (response == null) {
                        success = false;
                    } else {
                        // 查询到用户名可用
                        success = "00".equals(response.getCode());
                        tips = response.getMsg();
                    }
                    notifyCheckRegisterUserResult(success, tips, telphone);
                }
            });
        }
    }

    @Override
    public void registerByCellphone(String telphone, String password, String captcha) {
        Log.d(Log.TAG, "telphone : " + telphone);
        // 临时记录注册所需的信息
        mTmpAccount = telphone;
        mTmpPassoword = password;
        if (verifyCellphone(telphone) && verifyPassword(password) && verifyCaptcha(captcha)) {
            String title = mContext.getString(Utils.getStringId(mContext,
                    "jy_activity_register_by_cellphone"));
            String content = mContext.getString(Utils.getStringId(mContext,
                    "jy_activity_register_wait"));
            showProgress(null, title, content);
            checkCaptcha(telphone, captcha);
        }
    }

    @Override
    public void registerByUsername(String account, String password) {
        mTmpAccount = account;
        mTmpPassoword = password;
        if (verifyUsername(account) && verifyPassword(password)) { // 验证合法性
            String title = mContext.getString(Utils.getStringId(mContext,
                    "jy_activity_register_by_username"));
            String content = mContext.getString(Utils.getStringId(mContext,
                    "jy_activity_register_wait"));
            showProgress(null, title, content);
            mUserRequest.registerByUserName(account, password, new ResponseCallback<User>() {
                @Override
                public void onCallback(Response<User> response) {
                    boolean success = false;
                    String tips = null;
                    User user = null;
                    if (response == null) {
                        success = false;
                        tips = mContext.getString(Utils.getStringId(mContext, "jy_reg_failed"));
                    } else {
                        success = "00".equals(response.getCode());
                        if (success) { // 注册成功
                            user = response.getObj();
                            tips = mContext.getString(Utils.getStringId(mContext, "jy_reg_success"));
                        } else { // 注册失败
                            tips = response.getMsg();
                        }
                    }
                    notifyRegisterResult(success, user, tips);
                }
            });
        }
    }

    @Override
    public List<User> loadUsers() {
        return UserManager.get(mContext).loadUsers();
    }

    @Override
    public User loadLoginUser() {
        return UserManager.get(mContext).loadCurrentUser();
    }

    @Override
    public boolean isRememberPassword() {
        return UserManager.get(mContext).isRememberPassword();
    }

    @Override
    public void showAgreement() {
        WebViewDialog.Params params = new WebViewDialog.Params();
        params.setTitle(mContext.getString(Utils.getStringId(mContext, "jy_title_activity_register")));
        params.setUrl("file:///android_asset/agreement.html");
        WebViewDialog dialog = new WebViewDialog(mContext, params);
        dialog.show();
    }

    @Override
    public void showForgetPassword() {
        WebViewDialog.Params params = new WebViewDialog.Params();
        params.setUrl("https://passport.9you.com/m/getpasswd.php");
        params.setTitle(mContext.getString(Utils.getStringId(mContext, "jy_login_dialog_forgot")));
        WebViewDialog dialog = new WebViewDialog(mContext, params);
        dialog.show();
    }

    @Override
    public void showCustomerService() {
        WebViewDialog.Params params = new WebViewDialog.Params();
        params.setUrl("http://kf.9you.com/mobile/sds");
        params.setTitle(mContext.getString(Utils.getStringId(mContext, "jy_login_dialog_kf")));
        WebViewDialog dialog = new WebViewDialog(mContext, params);
        dialog.show();
    }

    @Override
    public void showAccountPopup(EditText editText) {
        AccountPopup popup = new AccountPopup(mContext, this);
        List<User> userList = loadUsers();
        popup.showPopup(editText, userList);
    }

    @Override
    public void fillUser(User user) {
        Log.d(Log.TAG, "");
        if (mLoginDialog != null) {
            mLoginDialog.setUserNameAndPassword(user.getUsername(), user.getPassword());
        }
    }

    @Override
    public void removeUser(User user) {
        Log.d(Log.TAG, "");
        UserManager.get(mContext).removeUser(user);
        if (mLoginDialog != null) {
            mLoginDialog.updateUserNameAndPassword();
        }
    }

    private void showUserCenter() {
        UserCenterDialog userCenterDialog = new UserCenterDialog(mContext, this);
        userCenterDialog.show();
    }

    @Override
    public void switchUser() {
        setOnUserLoginListener(new OnUserLoginListener() {
            @Override
            public void onLoginComplete(boolean success, String loginInfo) {
                if (mOnUserExchangeListener != null) {
                    mOnUserExchangeListener.onExchangeComplete(success, loginInfo);
                    mOnUserExchangeListener = null;
                }
            }
        });
        showLogin();
    }

    @Override
    public void login(OnUserLoginListener l) {
        mOnUserLoginListener = l;
        if (autoLogin()) {
            return;
        }
        showLogin();
    }

    @Override
    public void exchange(OnUserExchangeListener l) {
        mOnUserExchangeListener = l;
        showUserCenter();
    }

    @Override
    public void logout(OnUserLogoutListener l) {
        mOnUserLogoutListener = l;
        User user = UserManager.get(mContext).loadCurrentUser();
        String username = null;
        if (user != null) {
            username = user.getUsername();
        }
        UserManager.get(mContext).logout();
        if (mOnUserLogoutListener != null) {
            mOnUserLogoutListener.onLogoutComplete(!TextUtils.isEmpty(username), username);
        }
    }

    @Override
    public void exit(final WbSdk.OnExitCallback callback) {
        ExitDialog dialog = new ExitDialog(mContext);
        dialog.setOnExitCallback(new WbSdk.OnExitCallback() {
            @Override
            public void onExitConfirm() {
                if (callback != null) {
                    callback.onExitConfirm();
                }
            }

            @Override
            public void onExitCancel() {
                if (callback != null) {
                    callback.onExitCancel();
                }
            }
        });
        dialog.show();
    }
}